package com.sunxd.zstudy.juc;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author: ReentrantLock 可重入锁
 * 功能等同于synchronize 但是有优势
 * lock.tryLock 尝试得到这个锁
 * lock.lockInterruptibly(); 可被打断的加锁
 * new ReentrantLock(true) 公平锁-先进先执行
 *
 *   * 原理；cas + volita state + LockSupport
 *  lock()  cas state 从0变成1，如果失败（没有抢到锁），加入等待队列，双向莲表，
 *  unlock() 释放当前锁  state 从1 变成0 ，并通知下一个获取锁
 * @date: 2021-03-30 23:23
 **/
public class T09_ReentrantLook_02 {

    Lock lock = new ReentrantLock();
    private static  final  Lock fairLock = new ReentrantLock(true);

    public static void main(String[] args) {
        T09_ReentrantLook_02 t09_reentrantLook_02 = new T09_ReentrantLook_02();

         //lock.trylock 测试
//        new Thread(t09_reentrantLook_02::m1).start();
//        new Thread(t09_reentrantLook_02::m2).start();

        //lock.lockInterruptibly
//        new Thread(t09_reentrantLook_02::interrupt1).start();
         Thread thread2 = new Thread(t09_reentrantLook_02::interrupt2);
        thread2.start();
//         必须加 Thread.sleep
//        interrupt 太快了，线程还在调用就创建了，导致unlock是null
//        try {
//            Thread.sleep(1000);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
        thread2.interrupt();

        // 公平锁  公平竞争
//        new Thread(t09_reentrantLook_02::fairLock,"thread-1").start();
//        new Thread(t09_reentrantLook_02::fairLock,"thread-2").start();


    }

    void fairLock(){
        for (int i = 0; i < 10000; i++) {
            fairLock.lock();
            try {
                System.out.println(Thread.currentThread().getName() + "获得锁");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                fairLock.unlock();
            }
        }
    }

    void interrupt1(){
        lock.lock();
        try {
            System.out.println("t1 start");
            TimeUnit.SECONDS.sleep(Integer.MAX_VALUE);
            System.out.println("t1 end");
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    void interrupt2(){
        boolean flag =true;
        try {
            System.out.println("t2 start");
            lock.lockInterruptibly();
        } catch (InterruptedException e) {
            System.out.println(Thread.currentThread().getName() + " interrupted");
            flag = false;
        } finally {
            if(flag) {
                lock.unlock();
            }
        }
        System.out.println( " end ");
    }

    void m1(){
        lock.lock();
        try {
            for (int i = 0; i < 10; i++) {
                Thread.sleep(1000);
                System.out.println("m1  " + i);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    void m2(){
        boolean flag = false;
        try {
            flag = lock.tryLock(5, TimeUnit.SECONDS);
            System.out.println("m2..." + flag);
        } catch (InterruptedException  e) {
            e.printStackTrace();
        }finally {
            if(flag){
                lock.unlock();
            }
        }
    }
}
